//
// Created by zsl on 7/19/22.
//

#ifndef FISHJOY_SERVLET_HPP
#define FISHJOY_SERVLET_HPP

#include <functional>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "fishjoy/thread/thread.hpp"
#include "fishjoy/utils/util.hpp"
#include "http.hpp"
#include "http_session.hpp"

namespace fishjoy {
  namespace http {

    /**
 * @brief Servlet封装
     */
    class Servlet {
     public:
      /// 智能指针类型定义
      typedef std::shared_ptr<Servlet> ptr;

      /**
     * @brief 构造函数
     * @param[in] name 名称
       */
      Servlet(const std::string& name)
          :m_name(name) {}

      /**
     * @brief 析构函数
       */
      virtual ~Servlet() {}

      /**
     * @brief 处理请求
     * @param[in] request HTTP请求
     * @param[in] response HTTP响应
     * @param[in] session HTTP连接
     * @return 是否处理成功
       */
      virtual int32_t handle(fishjoy::http::HttpRequest::ptr request
                             , fishjoy::http::HttpResponse::ptr response
                             , fishjoy::http::HttpSession::ptr session) = 0;
                   
      /**
     * @brief 返回Servlet名称
       */
      const std::string& getName() const { return m_name;}
     protected:
      /// 名称
      std::string m_name;
    };

    /**
 * @brief 函数式Servlet
     */
    class FunctionServlet : public Servlet {
     public:
      /// 智能指针类型定义
      typedef std::shared_ptr<FunctionServlet> ptr;
      /// 函数回调类型定义
      typedef std::function<int32_t (fishjoy::http::HttpRequest::ptr request
                                    , fishjoy::http::HttpResponse::ptr response
                                    , fishjoy::http::HttpSession::ptr session)> callback;


      /**
     * @brief 构造函数
     * @param[in] cb 回调函数
       */
      FunctionServlet(callback cb);
      virtual int32_t handle(fishjoy::http::HttpRequest::ptr request
                             , fishjoy::http::HttpResponse::ptr response
                             , fishjoy::http::HttpSession::ptr session) override;
     private:
      /// 回调函数
      callback m_cb;
    };

    class IServletCreator {
     public:
      typedef std::shared_ptr<IServletCreator> ptr;
      virtual ~IServletCreator() {}
      virtual Servlet::ptr get() const = 0;
      virtual std::string getName() const = 0;
    };

    class HoldServletCreator : public IServletCreator {
     public:
      typedef std::shared_ptr<HoldServletCreator> ptr;
      HoldServletCreator(Servlet::ptr slt)
          :m_servlet(slt) {
      }

      Servlet::ptr get() const override {
        return m_servlet;
      }

      std::string getName() const override {
        return m_servlet->getName();
      }
     private:
      Servlet::ptr m_servlet;
    };

    template<class T>
    class ServletCreator : public IServletCreator {
     public:
      using ptr = std::shared_ptr<ServletCreator>;

      ServletCreator() {
      }

      Servlet::ptr get() const override {
        return Servlet::ptr(new T);
      }

      std::string getName() const override {
        return TypeToName<T>();
      }
    };

    /**
 * @brief Servlet分发器
     */
    class ServletDispatch : public Servlet {
     public:
      /// 智能指针类型定义
      typedef std::shared_ptr<ServletDispatch> ptr;
      /// 读写锁类型定义
      typedef RWMutex RWMutexType;

      /**
     * @brief 构造函数
       */
      ServletDispatch();
      virtual int32_t handle(fishjoy::http::HttpRequest::ptr request
                             , fishjoy::http::HttpResponse::ptr response
                             , fishjoy::http::HttpSession::ptr session) override;

      /**
     * @brief 添加servlet
     * @param[in] uri uri
     * @param[in] slt servlet
       */
      void addServlet(const std::string& uri, Servlet::ptr slt);

      /**
     * @brief 添加servlet
     * @param[in] uri uri
     * @param[in] cb FunctionServlet回调函数
       */
      void addServlet(const std::string& uri, FunctionServlet::callback cb);

      /**
     * @brief 添加模糊匹配servlet
     * @param[in] uri uri 模糊匹配 /fishjoy_*
     * @param[in] slt servlet
       */
      void addGlobServlet(const std::string& uri, Servlet::ptr slt);

      /**
     * @brief 添加模糊匹配servlet
     * @param[in] uri uri 模糊匹配 /fishjoy_*
     * @param[in] cb FunctionServlet回调函数
       */
      void addGlobServlet(const std::string& uri, FunctionServlet::callback cb);

      void addServletCreator(const std::string& uri, IServletCreator::ptr creator);
      void addGlobServletCreator(const std::string& uri, IServletCreator::ptr creator);

      template<class T>
      void addServletCreator(const std::string& uri) {
        addServletCreator(uri, std::make_shared<ServletCreator<T> >());
      }

      template<class T>
      void addGlobServletCreator(const std::string& uri) {
        addGlobServletCreator(uri, std::make_shared<ServletCreator<T> >());
      }

      /**
     * @brief 删除servlet
     * @param[in] uri uri
       */
      void delServlet(const std::string& uri);

      /**
     * @brief 删除模糊匹配servlet
     * @param[in] uri uri
       */
      void delGlobServlet(const std::string& uri);

      /**
     * @brief 返回默认servlet
       */
      Servlet::ptr getDefault() const { return m_default;}

      /**
     * @brief 设置默认servlet
     * @param[in] v servlet
       */
      void setDefault(Servlet::ptr v) { m_default = v;}


      /**
     * @brief 通过uri获取servlet
     * @param[in] uri uri
     * @return 返回对应的servlet
       */
      Servlet::ptr getServlet(const std::string& uri);

      /**
     * @brief 通过uri获取模糊匹配servlet
     * @param[in] uri uri
     * @return 返回对应的servlet
       */
      Servlet::ptr getGlobServlet(const std::string& uri);

      /**
     * @brief 通过uri获取servlet
     * @param[in] uri uri
     * @return 优先精准匹配,其次模糊匹配,最后返回默认
       */
      Servlet::ptr getMatchedServlet(const std::string& uri);

      void listAllServletCreator(std::map<std::string, IServletCreator::ptr>& infos);
      void listAllGlobServletCreator(std::map<std::string, IServletCreator::ptr>& infos);
     private:
      /// 读写互斥量
      RWMutexType m_mutex;
      /// 精准匹配servlet MAP
      /// uri(/fishjoy/xxx) -> servlet
      std::unordered_map<std::string, IServletCreator::ptr> m_datas;
      /// 模糊匹配servlet 数组
      /// uri(/fishjoy/*) -> servlet
      std::vector<std::pair<std::string, IServletCreator::ptr> > m_globs;
      /// 默认servlet，所有路径都没匹配到时使用
      Servlet::ptr m_default;
    };

    /**
 * @brief NotFoundServlet(默认返回404)
     */
    class NotFoundServlet : public Servlet {
     public:
      /// 智能指针类型定义
      typedef std::shared_ptr<NotFoundServlet> ptr;
      /**
     * @brief 构造函数
       */
      NotFoundServlet(const std::string& name);
      virtual int32_t handle(fishjoy::http::HttpRequest::ptr request
                             , fishjoy::http::HttpResponse::ptr response
                             , fishjoy::http::HttpSession::ptr session) override;

     private:
      std::string m_name;
      std::string m_content;
    };

  }
}

#endif  // FISHJOY_SERVLET_HPP
